
package JET.UtilPanels.Trees;

import JET.Centers.ControlCenter;
import JET.SA.SA_Dialogs;
import JET.SA.SA_Selection;
import JET.SA.SA_SpringBody;
import JET.Scene;
import JET.SwingUtils.*;
import JET.geom.Vec2d;
import JET.physics.*;
import JET.physics.bodies.SpringBody;
import JET.physics.bodies.SpringBody.RSpringsTreeNode;
import JET.physics.engine.JETContext;
import JET.physics.engine.SpringsTreeNode;
import JET.physics.interfaces.SceneTreeNode;
import java.util.Collection;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;

/**
 *
 * @author 057Ry
 */
public class SceneTree extends JTree {

    private static ControlCenter CC = ControlCenter.getInstance();

    private boolean autorefresh = false;
    private Scene scene;

    public SceneTree() {
        super();
        addTreeSelectionListener(new SceneTreeSelectionListener());
    }

    public void setScene(Scene scene) {
        this.scene = scene;
    }
    public void setAutorefresh(boolean b) {
        autorefresh = b;
    }
    public boolean isAutorefresh() { return autorefresh; }

//        @Override
//        protected void setExpandedState(TreePath path, boolean state) {
//            if (state) {
//                System.out.println("state: "+state);
//                super.setExpandedState(path, state);
//            }
//        }

    public class SceneTreeSelectionListener implements TreeSelectionListener {

        public void valueChanged(TreeSelectionEvent e) {
            final TreeSelectionEvent evt = e;
            final TreePath[] paths = e.getPaths();

            new Thread( new Runnable() {
                public void run() {
                    for (TreePath path : paths)
                        if (!evt.isAddedPath(path))
                            removePathFromSelection(path);

                    for (TreePath path : paths)
                        if (evt.isAddedPath(path))
                            addPathToSelection(path);

                    SA_Dialogs.fillPropertiesDialogWithMassData(scene);
                    SA_Dialogs.fillPropertiesDialogWithSpringData(scene);
                    SA_Dialogs.fillPropertiesDialogWithRSpringData(scene);

                    CC.GUIC.repaintAllSceneTabs();
                }
            }).start();
        }

        public void addPathToSelection(TreePath path) {
            Object last = path.getLastPathComponent();

            if      (last instanceof Mass) {
                SA_Selection.addMassToSelection((Mass) last, scene, false);
                //SA_Dialogs.fillPropertiesDialogWithMassData(scene);
            }
            else if (last instanceof Spring) {
                SA_Selection.addSpringToSelection((Spring) last, scene, false);
                //SA_Dialogs.fillPropertiesDialogWithSpringData(scene);
            }
            else if (last instanceof RSpring) {
                SA_Selection.addRSpringToSelection((RSpring) last, scene, false);
                //SA_Dialogs.fillPropertiesDialogWithRSpringData(scene);
            }
            else if (last instanceof Wall) {
                SA_Selection.addWallToSelection((Wall) last, scene, false);
            }
            ////////////////////////////////////////////////////////////////
            //                    SPRING BODY NODES                       //
            ////////////////////////////////////////////////////////////////
            else if (last instanceof SpringBody) SA_SpringBody.setCurrentSpringBody((SpringBody) last, scene, false);
            else if (last instanceof SpringBody.MassesTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                Collection<Mass> massCol = sb.getMassListSync();
                synchronized(massCol) {
                    for(Mass m : massCol)
                        SA_Selection.addMassToSelection(m, scene, false);
                }

                //SA_Dialogs.fillPropertiesDialogWithMassData(scene);
            }
            else if (last instanceof SpringBody.SpringsTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                scene.EC.selectionGroup.addSprings(sb.getSpringList());
                //SA_Dialogs.fillPropertiesDialogWithSpringData(scene);
            }
            else if (last instanceof SpringBody.RSpringsTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                scene.EC.selectionGroup.addRSprings(sb.getRSpringList());
                //SA_Dialogs.fillPropertiesDialogWithRSpringData(scene);
            }
            else if (last instanceof SpringBody.SMSpringsTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                for(Spring s : sb.getSMSprings())
                    SA_Selection.addSpringToSelection(s, scene, false);
                //SA_Dialogs.fillPropertiesDialogWithSpringData(scene);
            }
            else if (last instanceof SpringBody.WallsTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                SceneTree.this.scene.EC.selectionGroup.addWalls(sb.getBorder().getWallList());
            }
            ////////////////////////////////////////////////////////////////
            //                       SCENE NODES                          //
            ////////////////////////////////////////////////////////////////
            else if (last instanceof SpringBody.SpringsTreeNode) {
                JETContext engine = SceneTree.this.scene.getJETContext();
                for(Spring s : engine.springList)
                    SA_Selection.addSpringToSelection(s, SceneTree.this.scene, false);
            }
            else if (last instanceof SpringBody.RSpringsTreeNode) {
                JETContext engine = SceneTree.this.scene.getJETContext();
                for(RSpring rs : engine.rSpringList)
                    SA_Selection.addRSpringToSelection(rs, SceneTree.this.scene, false);
            }

            CC.GUIC.repaintAllSceneTabs();
        }

        public void removePathFromSelection(TreePath path) {
            Object last = path.getLastPathComponent();

            if      (last instanceof Mass) {
                SceneTree.this.scene.EC.selectionGroup.removeMass((Mass) last);
                //SA_Dialogs.fillPropertiesDialogWithMassData(scene);
            }
            else if (last instanceof Spring) {
                SceneTree.this.scene.EC.selectionGroup.removeSpring((Spring) last);
                //SA_Dialogs.fillPropertiesDialogWithSpringData(scene);
            }
            else if (last instanceof RSpring) {
                SceneTree.this.scene.EC.selectionGroup.removeRSpring((RSpring) last);
                //SA_Dialogs.fillPropertiesDialogWithRSpringData(scene);
            }
            else if (last instanceof Wall) SceneTree.this.scene.EC.selectionGroup.removeWall((Wall) last);
            ////////////////////////////////////////////////////////////////
            //                    SPRING BODY NODES                       //
            ////////////////////////////////////////////////////////////////
            else if (last instanceof SpringBody.MassesTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                SceneTree.this.scene.EC.selectionGroup.removeMasses(sb.getMassList());
                //SA_Dialogs.fillPropertiesDialogWithMassData(scene);
            }
            else if (last instanceof SpringBody.SpringsTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                SceneTree.this.scene.EC.selectionGroup.removeSprings(sb.getSpringList());
                //SA_Dialogs.fillPropertiesDialogWithSpringData(scene);
            }
            else if (last instanceof SpringBody.RSpringsTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                SceneTree.this.scene.EC.selectionGroup.removeRSprings(sb.getRSpringList());
                //SA_Dialogs.fillPropertiesDialogWithRSpringData(scene);
            }
            else if (last instanceof SpringBody.SMSpringsTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                for(Spring s : sb.getSMSprings())
                    SA_Selection.removeSpringFromSelection(s, SceneTree.this.scene, false);
                //SA_Dialogs.fillPropertiesDialogWithSpringData(scene);
            }
            else if (last instanceof SpringBody.WallsTreeNode) {
                SpringBody sb = (SpringBody) TreeUtil.getLastInstanceOfClassFromPath(path, SpringBody.class);
                SceneTree.this.scene.EC.selectionGroup.removeWalls(sb.getBorder().getWallList());
            }
            ////////////////////////////////////////////////////////////////
            //                       SCENE NODES                          //
            ////////////////////////////////////////////////////////////////
            else if (last instanceof SpringsTreeNode) {
                JETContext engine = SceneTree.this.scene.getJETContext();
                for(Spring s : engine.springList)
                    SA_Selection.removeSpringFromSelection(s, SceneTree.this.scene, false);
            }
            else if (last instanceof RSpringsTreeNode) {
                JETContext engine = SceneTree.this.scene.getJETContext();
                for(RSpring rs : engine.rSpringList)
                    SA_Selection.removeRSpringFromSelection(rs, SceneTree.this.scene, false);
            }

            CC.GUIC.repaintAllSceneTabs();
        }

    }

    public static class VecTreeNode implements  SceneTreeNode {

        Vec2d vec;
        String vecNodeName;

        public VecTreeNode(Vec2d v, String name) {
            vec = v;
            vecNodeName = name;
        }

        //public VecTreeNode(Vec2d position, String string) {
            //throw new UnsupportedOperationException("Not yet implemented");
        //}

        public SceneTreeNode getChild(int index) {return null;}
        public int getChildCount() {return 0;}
        public boolean isLeaf() {return true;}
        public int getIndexOfChild(Object child) {return -1;}

        public void resetNodeValue(Object o) {
            try {
                Double x = null, y = null;
                int comaIndex = o.toString().indexOf(',');
                // If no coma set X with given value
                if (comaIndex==-1)
                    try {
                        x = Double.parseDouble(o.toString());
                    } catch(NumberFormatException nfe) {}
                // Otherwise try setting X and Y
                else
                    try {
                        String strX = o.toString().substring(0, comaIndex);
                        String strY = o.toString().substring(comaIndex+1, o.toString().length());
                        x = Double.parseDouble(strX);
                        y = Double.parseDouble(strY);
                    } catch(NumberFormatException nfe) {}

                if (x!=null) vec.setX(x);
                if (y!=null) vec.setY(y);
                CC.GUIC.repaintAllSceneTabs();
            } catch(NumberFormatException nfe) {}
        }

        @Override
        public String toString() {
            return vecNodeName+": "+vec;
        }

        public String getVecNodeName() {
            return vecNodeName;
        }
    }
};
